package org.gstreamer.java.runtime;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.gstreamer.java.Activator;
import org.gstreamer.java.runtime.Environment.Position;
import org.osgi.framework.Bundle;

public class EnvironmentUtils {
	
	public final static String SHARED_LIBS_EXTENSION = "org.gstreamer.java.envSetup";
	
	public static List<String> updateEnvironment(){
		List<String> pathList = new ArrayList<String>();
		IExtensionRegistry registry = Platform.getExtensionRegistry();
		IExtensionPoint point = registry.getExtensionPoint(SHARED_LIBS_EXTENSION);
		if (point == null) 
			return null;
		// parse all extensions and update properties for each extension
		IExtension[] extensions = point.getExtensions();
		List<Environment> envList = new ArrayList<Environment>();
		for (IExtension extension: extensions){
			// parse extension
			envList.addAll(parseExtension(extension));
		}
		updateEnvironment(envList);
		return pathList;
	}

	public static void updateEnvironment(List<Environment> envList) {
		for (Environment environment : envList) {
			if (environment.isPathChain()){
				String pathChain = NativeUtil.getenv(environment.getName());
				pathChain = PathUtils.addToPathChain(pathChain, environment.getValue(), File.pathSeparator, true, PathUtils.Location.FIRST);
				NativeUtil.setenv(environment.getName(), pathChain);
			}else{
				NativeUtil.setenv(environment.getName(), environment.getValue());
			}
		}
	}

	public static String resolvePath(IExtension extension, String path) {
		String bundleName = extension.getContributor().getName();
		Bundle bundle = Platform.getBundle(bundleName);
		URL entry = bundle.getResource(path);
		if(entry == null){
			Activator.getDefault().logException("sharedLibs extension specifies the path to contribute, " +
					"but corresponding directory does not exist", 
					new FileNotFoundException(bundleName + ": " + path));
		}else{
			try {
				URL resolvedURL = FileLocator.resolve(entry);
				File fullPath = new File(resolvedURL.getPath());
				if (fullPath.exists()){
					return fullPath.getAbsolutePath();
				}else{
					Activator.getDefault().logException("Path does not exist (check if the bundle is jared)", 
							new FileNotFoundException(bundleName + ": " + fullPath.getAbsolutePath()));
				}
			} catch (IOException e) {
				Activator.getDefault().logException(e.getMessage(), e);
			}
		}
		return null;
	}

	public static boolean updateEnvironment(String path, String envName) {
		String pathChain = NativeUtil.getenv(envName);
		pathChain = PathUtils.addToPathChain(pathChain, path, File.pathSeparator, true, PathUtils.Location.FIRST);
		NativeUtil.setenv(envName, pathChain);
		return true;
	}

	public static String getPathEnvName(){
		if (Platform.getOS().equals(Platform.OS_WIN32)){
			return "PATH";
		}else{
			return "LD_LIBRARY_PATH";
		}
	}
	
	public static List<Environment> parseExtension(IExtension extension) {
		List<Environment> envList = new ArrayList<Environment>();
		IConfigurationElement[] elements = extension.getConfigurationElements();
		for (IConfigurationElement confElement : elements) {
			if (confElement.getName().equals("environment")){
				Environment env = new Environment();
				env.setName(confElement.getAttribute("name"));
				String value = confElement.getAttribute("value");
				boolean isPathChain = confElement.getAttribute("isPathChain").equals("true")? true: false;
				if (isPathChain){
					String path = resolvePath(extension, value);
					env.setPathChain(true);
					env.setValue(path);
				}else{
					env.setPathChain(false);
					env.setValue(value);
				}
				env.setPosition(Position.valueOf(confElement.getAttribute("position")));
				envList.add(env);
			}
		}
		return envList;
	}
}
